# coding=utf-8

"""
检查目录是否有更新文件，存在更新文件复制到脚本所在目录中
"""
import os,time,sys,inspect,getopt
import stat
import string
import ConfigParser

#获取脚本所在的路径
def current_path():   
    path=os.path.realpath(sys.path[0])  
    if os.path.isfile(path):  
        path=os.path.dirname(path)  
        return os.path.abspath(path)  
    else:  
        caller_file=inspect.stack()[1][1]  
        return os.path.abspath(os.path.dirname(caller_file))

#日期转时间戳        
def datetime_timestamp(dt):
  s = time.mktime(time.strptime(dt, '%Y-%m-%d %H:%M:%S'))
  return int(s)

#检查配置文件是否正确 
def checkini(config_file):
  try:
    ck_fp=open(config_file,'r')
    ck_fp.close()
  except:
    print u'配置文件config.ini不存在'
    sys.exit()
    
  ck_cf = ConfigParser.ConfigParser()
  try:
    ck_cf.read(config_file)
    foldernum=ck_cf.getint('folder','foldernum')
    if foldernum<1:
      print u'参数[folder]-foldernum'
      sys.exit()
    foldernames=[]
    for folderindex in xrange(1,foldernum+1):
      foldernames.append(ck_cf.get('folder',str(folderindex)))
    
    sections=ck_cf.sections()
    for foldername in foldernames:
      if 'moniter_'+foldername not in sections:
         print u'配置文件中缺少[moniter_'+foldername+u']段'
         sys.exit()
      moniter_folder = ck_cf.get('moniter_'+foldername,'moniter_folder') 

      if not os.path.exists(moniter_folder):
         print '[moniter_'+foldername+u'][moniter_folder]的目录'+moniter_folder+u'不存在'
         sys.exit()
         
      exclude_path = ck_cf.get('moniter_'+foldername,'exclude_path').replace('\\','/')
      if exclude_path!='':
        paths=string.split(exclude_path,',')
        for path in paths:
          if not os.path.exists(moniter_folder+path):
            print u'目录'+foldername+u':[moniter_'+foldername+u'][exclude_path]中的目录'+path+u'不存在'
            sys.exit()
                      
      lasttime= ck_cf.get('moniter_'+foldername,'lasttime')
      try: 
        datetime_timestamp(lasttime)
      except:
        print u'目录'+foldername+u':[moniter_'+foldername+u'][lasttime]参数格式不正确,应为2014-01-09 00:00:00'
        sys.exit()      
  except Exception,e:
    print u'检查配置文件失败'
    print e
    sys.exit()
  
def  usage():
  print u"-s 参数监视目录名 all-检查所有监视目录"
  print u"-l 列出监视的目录"
  print u"-h help"
  
class Check_file:
  def __init__(self,cf,foldername):
    self.foldername=foldername
    self.cf=cf
    self.moniter_folder = self.cf.get('moniter_'+self.foldername,'moniter_folder')
    self.exclude_path = self.cf.get('moniter_'+self.foldername,'exclude_path').replace('\\','/')
    self.lasttime= self.cf.get('moniter_'+self.foldername,'lasttime') 
    self.errorinfo='success'  #错误信息
    self.lfiles=[]  #本地文件列表
    try:
      os.chdir(self.moniter_folder)
    except:
      self.displaymsg(self.moniter_folder+u'目录不存在')
      self.writeLogs(self.moniter_folder+u'目录不存在')
      self.errorinfo='error'
      
  def __del__(self):
    pass

  def writeLogs(self,msg):
    global logfile
    msg=time.strftime('%Y-%m-%d %H:%M:%S')+'  '+u'[目录'+self.foldername+'] '+unicode(msg)+'\n'
    f=open(logfile,'a+')
    f.write(msg.encode('utf8'))
    f.close()
    
  def displaymsg(self,msg): 
    print u'目录'+self.foldername+' '+unicode(msg)
       
      
  #更新最后上传时间
  def setLastTime(self):
    global config_file
    self.cf.set("moniter_"+self.foldername, "lasttime", time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
    self.cf.write(open(config_file, "w"))

  def walk_path(self,top):
    """ 
    Args:
        top: 相对web根目录的相对路径 
    """
    flist=[]
    for root, dirs, files in os.walk(top, topdown=False):
        for name in files:
            f=os.path.join(root, name).replace('\\','/')[len(top):]
            flist.append(f.decode('gbk'))
    return flist        

  def getFilesInFolder(self):
    if self.errorinfo!='success':
      return   
    self.lfiles.extend(self.walk_path(self.moniter_folder))
        
  def copy_all_file(self):
    global script_path
    if self.errorinfo!='success':
      return
    copyNum=0 #复制文件数量 
    successNum=0 #成功数量
    failNum=0 #失败数量
    lastTime=datetime_timestamp(self.lasttime)
    self.local_path = os.path.join(script_path, self.foldername)
    os.system('rd /S /Q '+self.local_path)
    if not os.path.exists(self.local_path):
      os.makedirs(self.local_path)
    
    self.writeLogs(u'开始复制文件')
    for line in self.lfiles:
        filename=line.strip() 
        
        #排除目录
        if self.exclude_path!='':
          exclude_paths= string.split(self.exclude_path,',')
          findpath=False
          for expath in exclude_paths:
            if expath+'/'==filename[0:len(expath)+1]:  #加斜杠防止不完全匹配
              self.displaymsg(u'排除目录'+expath+u'中的文件'+filename)
              self.writeLogs(u'排除目录'+expath+u'中的文件'+filename)
              findpath=True
              break
          if findpath:
            continue
                                       
        fullname=os.path.join(self.moniter_folder,filename)
        if os.path.isfile(fullname):
            _st=os.stat(fullname)
            st_mtime = _st[stat.ST_MTIME]        
            if st_mtime > lastTime:#如果从上次上传后，文件修改过     
              copyNum=copyNum+1
              self.displaymsg(u'复制文件'+fullname)
              self.writeLogs(u'复制文件'+fullname)
              failNum,successNum=self.copy_file(fullname,filename,failNum,successNum)                
    
    if  copyNum >0:
      self.displaymsg(u'共复制'+str(copyNum)+u'个文件,成功'+str(successNum)+u'个文件,失败'+str(failNum)+u'个文件')
      self.writeLogs(u'共复制'+str(copyNum)+u'个文件,成功'+str(successNum)+u'个文件,失败'+str(failNum)+u'个文件')
    else:
      self.displaymsg(u'没有复制文件')
      self.writeLogs(u'没有复制文件')
    if failNum==0:
      self.setLastTime()
  
  def copy_file(self,fullname,filename,failNum,successNum):
    file_handler = open(fullname,'rb')
    try:
        local_file=os.path.join(self.local_path,filename)
        open(local_file, "wb").write(file_handler.read()) 
    except Exception,e:
        try:
            os.chdir(self.local_path)
            folderdirs=os.path.dirname(filename).split('/')
            for folderdir in folderdirs:
              try:
                os.mkdir(folderdir)
              except:
                pass #忽略创建目录的错误
              os.chdir(folderdir)                               
            os.chdir(self.local_path)
            open(local_file, "wb").write(file_handler.read()) 
        except Exception,e:
            self.displaymsg(u'复制文件'+fullname+u'失败 '+unicode(e))
            self.writeLogs(u'复制文件'+fullname+u'失败 '+unicode(e))
            failNum=failNum+1
            return failNum,successNum
    finally:        
        file_handler.close()
    successNum=successNum+1
    return failNum,successNum
    
  def check_folder(self):
    self.getFilesInFolder()
    self.copy_all_file()
    

if __name__=='__main__':    
  if len(sys.argv)<=1:
    usage()
    sys.exit()
  
  folder=''
  listfolder=False  #是否列目录
  
  try:
    opts, args = getopt.getopt(sys.argv[1:], "hls:")
  except:
    usage()
    sys.exit()
         
  for op, value in opts:
      if op == "-h":
         usage()
         sys.exit()
      elif op == "-l":
         listfolder=True
      elif op== "-s":
         folder=value
      else:
         usage()
         sys.exit()
  
  script_path=current_path()
  riqi = time.strftime('%Y%m%d%H%M%S', time.localtime())
  log_path = os.path.join(script_path, 'log')
  if not os.path.exists(log_path):
    os.makedirs(log_path)
  logfile=os.path.join(script_path,'log',riqi+'_'+folder+'.log')
  
  config_file= os.path.join(script_path,'config.ini') 
  
  checkini(config_file)

  cf=ConfigParser.ConfigParser()
  cf.read(config_file)
  foldernum=cf.getint('folder','foldernum')
  foldernames=[]
  for folderindex in xrange(1,foldernum+1):
    foldernames.append(cf.get('folder',str(folderindex)))
  
  #列出站点
  if listfolder:
    for foldername in foldernames:
      print foldername
    sys.exit()
    
  if folder=='':
    usage()
    sys.exit()
  
  if folder!='all':
    if folder not in foldernames:
      print u'目录'+folder+u'不存在'
      sys.exit()
  
  for foldername in foldernames:
    if folder=='all':
      print u'检查目录'+foldername
      foldercheck=Check_file(cf,foldername)
      foldercheck.check_folder()
      del foldercheck   
    else:
      if folder==foldername:
        print u'检查目录'+foldername
        foldercheck=Check_file(cf,foldername)
        foldercheck.check_folder() 




